package gamemodels;

import gamecomponents.Leaderboard;
import gamecomponents.graphic.BlitData;
import gamecomponents.graphic.Blitable;
import gamecomponents.graphic.TextureHelper;
import gamecomponents.menu.MenuButton;
import gamecomponents.menu.MenuImage;
import gamecomponents.settings.GameSettings;
import input.InputManager;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;

import maze.MazeSize;

import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;

/**
 *	Shows the leaderboard for the 
 *	Small maze (10x10). 
 *	Possible expansions could include 
 *	options to view other maze sizes as well.
 * @author Team Deer
 */
public class LeaderBoardMenuModel extends Observable implements IGameModel {

	private static LeaderBoardMenuModel singletonInstance;
	private IGameModel nextModel;

	private final SimpleVector screenSize;

	private final MenuImage backgroundImage;

	private final MenuButton backButton;
	private final MenuButton resetButton;

	private boolean requestExit;

	private final List<Blitable> components;

	// Constructor and singleton getter

	/**
	 * Constructs a new LeaderBoardModel
	 */
	private LeaderBoardMenuModel() {
		this.screenSize = GameSettings.SCREEN_SIZE;

		this.requestExit = false;

		this.components = new LinkedList<Blitable>();

		this.backgroundImage = new MenuImage(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\menubackground.png"),
				0, 0, (int) this.screenSize.x, (int) this.screenSize.y, 255);
		this.components.add(this.backgroundImage);

		this.resetButton = new MenuButton(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\resetActive.png"),
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\resetInactive.png"),
				(int) (this.screenSize.x - (this.screenSize.x / 8) - 163),
				(int) (this.screenSize.y - (this.screenSize.y / 8) + 5), 163,
				48, 255);
		this.components.add(this.resetButton);

		this.backButton = new MenuButton(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\backActive.png"),
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\backInactive.png"),
				(int) (this.screenSize.x / 8), (int) (this.screenSize.y
						- (this.screenSize.y / 8) + 5), 210, 60, 255);
		this.components.add(this.backButton);

		super.setChanged();
	}

	
	/**
	 * @return the singleton instance
	 */
	public static LeaderBoardMenuModel getInstance() {
		if (singletonInstance == null) {
			singletonInstance = new LeaderBoardMenuModel();
		}
		return singletonInstance;
	}

	// Update

	
	@Override
	public void reset() {
		this.requestExit = false;
		this.nextModel = null;
	}

	
	@Override
	public boolean isRunning() {
		return !this.requestExit;
	}

	
	@Override
	public void update(final InputManager inputManager) {

		// Go back to Main Menu
		if (inputManager.getKeyboardState().isKeyPressed(KeyEvent.VK_ESCAPE)
				|| (inputManager.getKeyboardState()
						.isKeyPressed(KeyEvent.VK_BACK_SPACE))) {
			this.changeModel(MainMenuModel.getInstance());
		}

		// Let the buttons read input...
		this.updateButtons(inputManager);

		// Does View want to know?
		if (this.backButton.hasChanged() || this.resetButton.hasChanged()) {
			super.setChanged();
		}

		super.notifyObservers();
	}

	
	/**
	 * Updates the buttons
	 * @param inputManager the inputmanager
	 */
	private void updateButtons(final InputManager inputManager) {

		// Check for interaction with buttons
		this.backButton.update(inputManager);
		this.resetButton.update(inputManager);

		// Perfrom actions
		if (inputManager.mouseIsClicked()) {
			if (this.backButton.pointIsOver(inputManager.getMousePosition())) {
				this.changeModel(MainMenuModel.getInstance());
			}
			if (this.resetButton.pointIsOver(inputManager.getMousePosition())) {
				Leaderboard.getInstance().reset();
				super.setChanged();
			}
		}
	}

	
	/**
	 * Tells the Controller to change model
	 * @param model the new model to run.
	 */
	private void changeModel(final IGameModel model) {
		this.nextModel = model;
	}

	
	@Override
	public IGameModel getNextModel() {
		return this.nextModel;
	}

	// Viewhelp

	
	@Override
	public List<BlitData> getBlitData() {
		final List<BlitData> list = new LinkedList<BlitData>();

		for (final Blitable data : this.components) {
			list.add(new BlitData(
					data.getTexture(), // texture
					0 /* srcX */, 0 /* srcY */, data.getPosition().x /* destX */,
					data.getPosition().y /* destY */,
					data.getSrcWidth() /* sourceWidth */,
					data.getSrcHeight() /* sourceHeight */,
					data.getWidth() /* destWidth */,
					data.getHeight() /* destHeight */, 255 /* transValue */,
					false /* additive */, null)); /* addColor */
		}
		// Add transparent texture
		list.add(new BlitData(
				TextureHelper.getSemiTransparentTexture(), // texture
				0 /* srcX */, 0 /* srcY */,
				(int) (GameSettings.SCREEN_SIZE.x / 8) /* destX */,
				(int) (GameSettings.SCREEN_SIZE.y / 8)/* destY */,
				2 /* sourceWidth */, 2 /* sourceHeight */,
				(int) (6 * GameSettings.SCREEN_SIZE.x / 8) /* destWidth */,
				(int) (6 * GameSettings.SCREEN_SIZE.y / 8) /* destHeight */,
				255 /* transValue */, false /* additive */, null)); /* addColor */

		final BufferedImage img = new BufferedImage(
				(int) (6 * GameSettings.SCREEN_SIZE.x / 8),
				(int) (6 * GameSettings.SCREEN_SIZE.y / 8),
				BufferedImage.TYPE_INT_ARGB);
		final Graphics g = img.getGraphics();
		g.setFont(new Font("Segoe WP", Font.PLAIN, 36));

		for (int i = 0; i < Leaderboard.getInstance()
				.getLeaderBoardComponents(MazeSize.SMALL).size(); i++) {
			g.drawString(Leaderboard.getInstance().getLeaderBoardComponents(MazeSize.SMALL)
					.get(i).toFormattedString(), 20, 56 + i * 56);
		}

		final Texture leaderBoardTexture = new Texture(img);
		list.add(new BlitData(
				leaderBoardTexture, // texture
				0 /* srcX */, 0 /* srcY */,
				(int) (GameSettings.SCREEN_SIZE.x / 8) /* destX */,
				(int) (GameSettings.SCREEN_SIZE.y / 8)/* destY */,
				leaderBoardTexture.getWidth() /* sourceWidth */,
				leaderBoardTexture.getHeight() /* sourceHeight */, img
						.getWidth() /* destWidth */,
				img.getHeight() /* destHeight */, 255 /* transValue */,
				false /* additive */, null)); /* addColor */
		return list;
	}
	
}
